#include<stdio.h>

#include"constants.h"
#include"bitboards.h"
#include"magic.h"

#ifdef _MSC_VER
	#pragma message("Compilam pe MSC -- dam disable la 4312 si 4146") /* me enervau astea cu unary operator applied crap 8-| */
	#pragma warning( disable : 4312)
	#pragma warning( disable : 4146)
#endif

U64 FileMasks[8];		/* Numbers representing the vertical files of the chess board */
U64 IsolaniMasks[8];	/* Numbers representing bit masks to locate isolani masks */

U64 MagicMoves_PawnEnPas_DB[2][64];
U64 MagicMoves_Pawns_DB[2][64];	/* Pawn moves database */
U64 MagicMoves_Knight_DB[64];	/* Knight moves database */
U64 MagicMoves_King_DB[64];		/* King moves database */

const U64 CastleMasks[2][2] =
{
	{ QSC_WHITE_MASK, KSC_WHITE_MASK },
	{ QSC_BLACK_MASK, KSC_BLACK_MASK }
};

#ifdef MINIMUM_MAGIC
U64 MagicMoves_Bishop_DB[5248];
const unsigned int MagicShiftsBishop[64] = 
{
	58, 59, 59, 59, 59, 59, 59, 58,
	59, 59, 59, 59, 59, 59, 59, 59,
	59, 59, 57, 57, 57, 57, 59, 59,
	59, 59, 57, 55, 55, 57, 59, 59,
	59, 59, 57, 55, 55, 57, 59, 59,
	59, 59, 57, 57, 57, 57, 59, 59,
	59, 59, 59, 59, 59, 59, 59, 59,
	58, 59, 59, 59, 59, 59, 59, 58
};
const U64 *MagicIndexesBishop[64] = 
{
	MagicMoves_Bishop_DB + 4992,MagicMoves_Bishop_DB + 2624,MagicMoves_Bishop_DB + 256,MagicMoves_Bishop_DB + 896,
	MagicMoves_Bishop_DB + 1280,MagicMoves_Bishop_DB + 1664,MagicMoves_Bishop_DB + 4800,MagicMoves_Bishop_DB + 5120,
	MagicMoves_Bishop_DB + 2560,MagicMoves_Bishop_DB + 2656,MagicMoves_Bishop_DB + 288,MagicMoves_Bishop_DB + 928,
	MagicMoves_Bishop_DB + 1312,MagicMoves_Bishop_DB + 1696,MagicMoves_Bishop_DB + 4832,MagicMoves_Bishop_DB + 4928,
	MagicMoves_Bishop_DB + 0,MagicMoves_Bishop_DB + 128,MagicMoves_Bishop_DB + 320,MagicMoves_Bishop_DB + 960,
	MagicMoves_Bishop_DB + 1344,MagicMoves_Bishop_DB + 1728,MagicMoves_Bishop_DB + 2304,MagicMoves_Bishop_DB + 2432,
	MagicMoves_Bishop_DB + 32,MagicMoves_Bishop_DB + 160,MagicMoves_Bishop_DB + 448,MagicMoves_Bishop_DB + 2752,
	MagicMoves_Bishop_DB + 3776,MagicMoves_Bishop_DB + 1856,MagicMoves_Bishop_DB + 2336,MagicMoves_Bishop_DB + 2464,
	MagicMoves_Bishop_DB + 64,MagicMoves_Bishop_DB + 192,MagicMoves_Bishop_DB + 576,MagicMoves_Bishop_DB + 3264,
	MagicMoves_Bishop_DB + 4288,MagicMoves_Bishop_DB + 1984,MagicMoves_Bishop_DB + 2368,MagicMoves_Bishop_DB + 2496,
	MagicMoves_Bishop_DB + 96,MagicMoves_Bishop_DB + 224,MagicMoves_Bishop_DB + 704,MagicMoves_Bishop_DB + 1088,
	MagicMoves_Bishop_DB + 1472,MagicMoves_Bishop_DB + 2112,MagicMoves_Bishop_DB + 2400,MagicMoves_Bishop_DB + 2528,
	MagicMoves_Bishop_DB + 2592,MagicMoves_Bishop_DB + 2688,MagicMoves_Bishop_DB + 832,MagicMoves_Bishop_DB + 1216,
	MagicMoves_Bishop_DB + 1600,MagicMoves_Bishop_DB + 2240,MagicMoves_Bishop_DB + 4864,MagicMoves_Bishop_DB + 4960,
	MagicMoves_Bishop_DB + 5056,MagicMoves_Bishop_DB + 2720,MagicMoves_Bishop_DB + 864,MagicMoves_Bishop_DB + 1248,
	MagicMoves_Bishop_DB + 1632,MagicMoves_Bishop_DB + 2272,MagicMoves_Bishop_DB + 4896,MagicMoves_Bishop_DB + 5184
};
#else
	#ifndef HASH_PERFECT_MAGIC
		U64 MagicMoves_Bishop_DB[64][1 << 9];
	#else
		U64 MagicMoves_Bishop_DB[1428];
		HASH_PERFECT_MAGIC MagicIndexesBishop[64][1 << 9];
	#endif
#endif

const U64 MagicNumbers_Bishop[64] = 
{
	0x0002020202020200ULL,0x0002020202020000ULL,0x0004010202000000ULL,0x0004040080000000ULL,
	0x0001104000000000ULL,0x0000821040000000ULL,0x0000410410400000ULL,0x0000104104104000ULL,
	0x0000040404040400ULL,0x0000020202020200ULL,0x0000040102020000ULL,0x0000040400800000ULL,
	0x0000011040000000ULL,0x0000008210400000ULL,0x0000004104104000ULL,0x0000002082082000ULL,
	0x0004000808080800ULL,0x0002000404040400ULL,0x0001000202020200ULL,0x0000800802004000ULL,
	0x0000800400A00000ULL,0x0000200100884000ULL,0x0000400082082000ULL,0x0000200041041000ULL,
	0x0002080010101000ULL,0x0001040008080800ULL,0x0000208004010400ULL,0x0000404004010200ULL,
	0x0000840000802000ULL,0x0000404002011000ULL,0x0000808001041000ULL,0x0000404000820800ULL,
	0x0001041000202000ULL,0x0000820800101000ULL,0x0000104400080800ULL,0x0000020080080080ULL,
	0x0000404040040100ULL,0x0000808100020100ULL,0x0001010100020800ULL,0x0000808080010400ULL,
	0x0000820820004000ULL,0x0000410410002000ULL,0x0000082088001000ULL,0x0000002011000800ULL,
	0x0000080100400400ULL,0x0001010101000200ULL,0x0002020202000400ULL,0x0001010101000200ULL,
	0x0000410410400000ULL,0x0000208208200000ULL,0x0000002084100000ULL,0x0000000020880000ULL,
	0x0000001002020000ULL,0x0000040408020000ULL,0x0004040404040000ULL,0x0002020202020000ULL,
	0x0000104104104000ULL,0x0000002082082000ULL,0x0000000020841000ULL,0x0000000000208800ULL,
	0x0000000010020200ULL,0x0000000404080200ULL,0x0000040404040400ULL,0x0002020202020200ULL
};
const U64 MagicMask_Bishop[64] = 
{
	0x0040201008040200ULL,0x0000402010080400ULL,0x0000004020100A00ULL,0x0000000040221400ULL,
	0x0000000002442800ULL,0x0000000204085000ULL,0x0000020408102000ULL,0x0002040810204000ULL,
	0x0020100804020000ULL,0x0040201008040000ULL,0x00004020100A0000ULL,0x0000004022140000ULL,
	0x0000000244280000ULL,0x0000020408500000ULL,0x0002040810200000ULL,0x0004081020400000ULL,
	0x0010080402000200ULL,0x0020100804000400ULL,0x004020100A000A00ULL,0x0000402214001400ULL,
	0x0000024428002800ULL,0x0002040850005000ULL,0x0004081020002000ULL,0x0008102040004000ULL,
	0x0008040200020400ULL,0x0010080400040800ULL,0x0020100A000A1000ULL,0x0040221400142200ULL,
	0x0002442800284400ULL,0x0004085000500800ULL,0x0008102000201000ULL,0x0010204000402000ULL,
	0x0004020002040800ULL,0x0008040004081000ULL,0x00100A000A102000ULL,0x0022140014224000ULL,
	0x0044280028440200ULL,0x0008500050080400ULL,0x0010200020100800ULL,0x0020400040201000ULL,
	0x0002000204081000ULL,0x0004000408102000ULL,0x000A000A10204000ULL,0x0014001422400000ULL,
	0x0028002844020000ULL,0x0050005008040200ULL,0x0020002010080400ULL,0x0040004020100800ULL,
	0x0000020408102000ULL,0x0000040810204000ULL,0x00000A1020400000ULL,0x0000142240000000ULL,
	0x0000284402000000ULL,0x0000500804020000ULL,0x0000201008040200ULL,0x0000402010080400ULL,
	0x0002040810204000ULL,0x0004081020400000ULL,0x000A102040000000ULL,0x0014224000000000ULL,
	0x0028440200000000ULL,0x0050080402000000ULL,0x0020100804020000ULL,0x0040201008040200ULL
};

#ifdef MINIMUM_MAGIC
U64 MagicMoves_Rook_DB[102400];
const unsigned int MagicShiftsRook[64] = 
{
	52, 53, 53, 53, 53, 53, 53, 52,
	53, 54, 54, 54, 54, 54, 54, 53,
	53, 54, 54, 54, 54, 54, 54, 53,
	53, 54, 54, 54, 54, 54, 54, 53,
	53, 54, 54, 54, 54, 54, 54, 53,
	53, 54, 54, 54, 54, 54, 54, 53,
	53, 54, 54, 54, 54, 54, 54, 53,
	52, 53, 53, 53, 53, 53, 53, 52
};
const U64 *MagicIndexesRook[64] = 
{
	MagicMoves_Rook_DB + 86016,MagicMoves_Rook_DB + 73728,MagicMoves_Rook_DB + 36864,MagicMoves_Rook_DB + 43008,
	MagicMoves_Rook_DB + 47104,MagicMoves_Rook_DB + 51200,MagicMoves_Rook_DB + 77824,MagicMoves_Rook_DB + 94208,
	MagicMoves_Rook_DB + 69632,MagicMoves_Rook_DB + 32768,MagicMoves_Rook_DB + 38912,MagicMoves_Rook_DB + 10240,
	MagicMoves_Rook_DB + 14336,MagicMoves_Rook_DB + 53248,MagicMoves_Rook_DB + 57344,MagicMoves_Rook_DB + 81920,
	MagicMoves_Rook_DB + 24576,MagicMoves_Rook_DB + 33792,MagicMoves_Rook_DB + 6144,MagicMoves_Rook_DB + 11264,
	MagicMoves_Rook_DB + 15360,MagicMoves_Rook_DB + 18432,MagicMoves_Rook_DB + 58368,MagicMoves_Rook_DB + 61440,
	MagicMoves_Rook_DB + 26624,MagicMoves_Rook_DB + 4096,MagicMoves_Rook_DB + 7168,MagicMoves_Rook_DB + 0,
	MagicMoves_Rook_DB + 2048,MagicMoves_Rook_DB + 19456,MagicMoves_Rook_DB + 22528,MagicMoves_Rook_DB + 63488,
	MagicMoves_Rook_DB + 28672,MagicMoves_Rook_DB + 5120,MagicMoves_Rook_DB + 8192,MagicMoves_Rook_DB + 1024,
	MagicMoves_Rook_DB + 3072,MagicMoves_Rook_DB + 20480,MagicMoves_Rook_DB + 23552,MagicMoves_Rook_DB + 65536,
	MagicMoves_Rook_DB + 30720,MagicMoves_Rook_DB + 34816,MagicMoves_Rook_DB + 9216,MagicMoves_Rook_DB + 12288,
	MagicMoves_Rook_DB + 16384,MagicMoves_Rook_DB + 21504,MagicMoves_Rook_DB + 59392,MagicMoves_Rook_DB + 67584,
	MagicMoves_Rook_DB + 71680,MagicMoves_Rook_DB + 35840,MagicMoves_Rook_DB + 39936,MagicMoves_Rook_DB + 13312,
	MagicMoves_Rook_DB + 17408,MagicMoves_Rook_DB + 54272,MagicMoves_Rook_DB + 60416,MagicMoves_Rook_DB + 83968,
	MagicMoves_Rook_DB + 90112,MagicMoves_Rook_DB + 75776,MagicMoves_Rook_DB + 40960,MagicMoves_Rook_DB + 45056,
	MagicMoves_Rook_DB + 49152,MagicMoves_Rook_DB + 55296,MagicMoves_Rook_DB + 79872,MagicMoves_Rook_DB + 98304
};
#else
	#ifndef HASH_PERFECT_MAGIC
		U64 MagicMoves_Rook_DB[64][1 << 12];
	#else
		U64 MagicMoves_Rook_DB[4900];
		HASH_PERFECT_MAGIC MagicIndexesRook[64][1<<12];
	#endif
#endif

//0xEA87FFFECBFEA5AE -- H8 11 bit key for Rooks

const U64 MagicNumbers_Rook[64] = 
{
	0x0080001020400080ULL,0x0040001000200040ULL,0x0080081000200080ULL,0x0080040800100080ULL,
	0x0080020400080080ULL,0x0080010200040080ULL,0x0080008001000200ULL,0x0080002040800100ULL,
	0x0000800020400080ULL,0x0000400020005000ULL,0x0000801000200080ULL,0x0000800800100080ULL,
	0x0000800400080080ULL,0x0000800200040080ULL,0x0000800100020080ULL,0x0000800040800100ULL,
	0x0000208000400080ULL,0x0000404000201000ULL,0x0000808010002000ULL,0x0000808008001000ULL,
	0x0000808004000800ULL,0x0000808002000400ULL,0x0000010100020004ULL,0x0000020000408104ULL,
	0x0000208080004000ULL,0x0000200040005000ULL,0x0000100080200080ULL,0x0000080080100080ULL,
	0x0000040080080080ULL,0x0000020080040080ULL,0x0000010080800200ULL,0x0000800080004100ULL,
	0x0000204000800080ULL,0x0000200040401000ULL,0x0000100080802000ULL,0x0000080080801000ULL,
	0x0000040080800800ULL,0x0000020080800400ULL,0x0000020001010004ULL,0x0000800040800100ULL,
	0x0000204000808000ULL,0x0000200040008080ULL,0x0000100020008080ULL,0x0000080010008080ULL,
	0x0000040008008080ULL,0x0000020004008080ULL,0x0000010002008080ULL,0x0000004081020004ULL,
	0x0000204000800080ULL,0x0000200040008080ULL,0x0000100020008080ULL,0x0000080010008080ULL,
	0x0000040008008080ULL,0x0000020004008080ULL,0x0000800100020080ULL,0x0000800041000080ULL,
	0x0000102040800101ULL,0x0000102040008101ULL,0x0000081020004101ULL,0x0000040810002101ULL,
	0x0001000204080011ULL,0x0001000204000801ULL,0x0001000082000401ULL,0x0000002040810402ULL
};
const U64 MagicMask_Rook[64] = 
{
	0x000101010101017EULL,0x000202020202027CULL,0x000404040404047AULL,0x0008080808080876ULL,
	0x001010101010106EULL,0x002020202020205EULL,0x004040404040403EULL,0x008080808080807EULL,
	0x0001010101017E00ULL,0x0002020202027C00ULL,0x0004040404047A00ULL,0x0008080808087600ULL,
	0x0010101010106E00ULL,0x0020202020205E00ULL,0x0040404040403E00ULL,0x0080808080807E00ULL,
	0x00010101017E0100ULL,0x00020202027C0200ULL,0x00040404047A0400ULL,0x0008080808760800ULL,
	0x00101010106E1000ULL,0x00202020205E2000ULL,0x00404040403E4000ULL,0x00808080807E8000ULL,
	0x000101017E010100ULL,0x000202027C020200ULL,0x000404047A040400ULL,0x0008080876080800ULL,
	0x001010106E101000ULL,0x002020205E202000ULL,0x004040403E404000ULL,0x008080807E808000ULL,
	0x0001017E01010100ULL,0x0002027C02020200ULL,0x0004047A04040400ULL,0x0008087608080800ULL,
	0x0010106E10101000ULL,0x0020205E20202000ULL,0x0040403E40404000ULL,0x0080807E80808000ULL,
	0x00017E0101010100ULL,0x00027C0202020200ULL,0x00047A0404040400ULL,0x0008760808080800ULL,
	0x00106E1010101000ULL,0x00205E2020202000ULL,0x00403E4040404000ULL,0x00807E8080808000ULL,
	0x007E010101010100ULL,0x007C020202020200ULL,0x007A040404040400ULL,0x0076080808080800ULL,
	0x006E101010101000ULL,0x005E202020202000ULL,0x003E404040404000ULL,0x007E808080808000ULL,
	0x7E01010101010100ULL,0x7C02020202020200ULL,0x7A04040404040400ULL,0x7608080808080800ULL,
	0x6E10101010101000ULL,0x5E20202020202000ULL,0x3E40404040404000ULL,0x7E80808080808000ULL
};

const void InitFileMasks() /* init file masks */
{
	int i;
	U64 bbAux=0;
	for(i=0;i<8;i++) FileMasks[0]|=((U64)1<<(i*8));
	for(i=1;i<8;i++) FileMasks[i]=FileMasks[0]<<i;
}

const void InitIsolaniMasks()
{
	int i;
	for(i=0;i<8;i++)
	{
		if(i)	IsolaniMasks[i]|=(FileMasks[i-1]);
		if(i<7) IsolaniMasks[i]|=(FileMasks[i+1]);
	}
}

const void InitPawnEnPassantMasks()
{
	int i;
	MagicMoves_PawnEnPas_DB[1][24]=(U64)1<<25;
	MagicMoves_PawnEnPas_DB[1][31]=(U64)1<<30;
	for(i=1;i<7;i++) MagicMoves_PawnEnPas_DB[1][24+i]=((U64)1<<(25+i))|((U64)1<<(23+i));

	MagicMoves_PawnEnPas_DB[0][32]=(U64)1<<33;
	MagicMoves_PawnEnPas_DB[0][39]=(U64)1<<38;
	for(i=1;i<7;i++) MagicMoves_PawnEnPas_DB[0][32+i]=((U64)1<<(33+i))|((U64)1<<(31+i));
}

const U64 InitMagicMoves_PW(const int square) /* init miscari magice pioni albi */
{
	int y=square/8,x=square%8;
	U64 bbPAttacks=0;
	if(y==1) bbPAttacks=PLACE_PIECE(bbPAttacks,COORDS_2_INDEX(3,x));
	if(y+1<=7)
	{
		bbPAttacks=PLACE_PIECE(bbPAttacks,COORDS_2_INDEX(y+1,x));
		if(x-1>=0)	bbPAttacks=PLACE_PIECE(bbPAttacks,COORDS_2_INDEX(y+1,x-1));
		if(x+1<=7)	bbPAttacks=PLACE_PIECE(bbPAttacks,COORDS_2_INDEX(y+1,x+1));
	}
	return bbPAttacks;
}

const U64 InitMagicMoves_PB(const int square) /* init miscari magice pioni negri */
{
	int y=square/8,x=square%8;
	U64 bbPAttacks=0;
	if(y==6) bbPAttacks=PLACE_PIECE(bbPAttacks,COORDS_2_INDEX(4,x));
	if(y-1>=0)
	{
		bbPAttacks=PLACE_PIECE(bbPAttacks,COORDS_2_INDEX(y-1,x));
		if(x-1>=0)	bbPAttacks=PLACE_PIECE(bbPAttacks,COORDS_2_INDEX(y-1,x-1));
		if(x+1<=7)	bbPAttacks=PLACE_PIECE(bbPAttacks,COORDS_2_INDEX(y-1,x+1));
	}
	return bbPAttacks;
}

const U64 InitMagicMoves_Ocupare(const int *squares, const int numSquares,const U64 linocc)
{
	int i;
	U64 ret=0;
	for(i=0;i<numSquares;i++)
		if(linocc & (((U64)(1))<<i))
			ret|=(((U64)(1))<<squares[i]);
	return ret;
}
/* Generate rook attack board based on occupancy board and square ( folosita mai incolo la generarea intregii baze de date ) */ 
const U64 InitMagicMoves_R(const int square, const U64 occ)
{
	U64 ret=0,bit;
	U64 rowbits=(((U64)0xFF)<<(8*(square/8)));
	bit=(((U64) (1))<<square);
	do						/* Generam in prima directie */
    {
		bit<<=8;
		ret|=bit;
    }while(bit && !(bit & occ));
	bit=(((U64)(1))<<square);
	do						/* Generam in a doua directie */
    {
		bit>>=8;
		ret|=bit;
    }while(bit && !(bit & occ));
	bit=(((U64)(1))<<square);
	do						/* Generam in a treia directie */
    {
		bit<<=1;
		if(bit & rowbits) ret |= bit;
		else break;
    }while(!(bit & occ));
	bit=(((U64)(1))<<square);
	do						/* Generam in a patra ( si ultima ) directie */
    {
		bit>>=1;
		if(bit & rowbits) ret|=bit;
		else break;
    }while(!(bit & occ));
	return ret;
}
/* Generate bishop attack board based on occupancy board and square ( folosita mai incolo la generarea intregii baze de date ) */ 
const U64 InitMagicMoves_B(const int square, const U64 occ)
{
	U64 ret=0,bit,bit2;
	U64 rowbits=(((U64)0xFF)<<(8*(square/8)));
	bit=(((U64)(1))<<square);
	bit2=bit;
	do				/* Generam in prima directie */
    {
		bit<<=8-1;
		bit2>>=1;
		if(bit2 & rowbits) ret|=bit;
		else break;
    }while(bit && !(bit & occ));
	bit=(((U64)(1))<<square);
	bit2=bit;
	do				/* Generam in a doua directie */
    {
		bit<<=8+1;
		bit2<<=1;
		if(bit2 & rowbits) ret|=bit;
		else break;
    }while(bit && !(bit&occ));
	bit=(((U64)(1))<<square);
	bit2=bit;
	do				/* Generam in a treia directie */
    {
		bit>>=8-1;
		bit2<<=1;
		if(bit2 & rowbits) ret|=bit;
		else break;
    }while(bit && !(bit & occ));
	bit=(((U64)(1))<<square);
	bit2=bit;
	do				/* Generam in a patra ( si ultima ) directie */
    {
		bit >>= 8 + 1;
		bit2 >>= 1;
		if(bit2 & rowbits) ret |= bit;
		else break;
    }while(bit && !(bit & occ));
  return ret;
}

/* Generate Knight attack board based on board square index */
const U64 InitMagicMoves_N(const int square)
{
	int y=square/8,x=square%8;
	U64 bbNAttacks=0;
	if(x-2>=0 && y-1>=0) bbNAttacks=PLACE_PIECE(bbNAttacks,COORDS_2_INDEX(y-1,x-2));
	if(x+2<=7 && y-1>=0) bbNAttacks=PLACE_PIECE(bbNAttacks,COORDS_2_INDEX(y-1,x+2));
	if(x+2<=7 && y+1<=7) bbNAttacks=PLACE_PIECE(bbNAttacks,COORDS_2_INDEX(y+1,x+2));
	if(x-2>=0 && y+1<=7) bbNAttacks=PLACE_PIECE(bbNAttacks,COORDS_2_INDEX(y+1,x-2));
	if(x-1>=0 && y-2>=0) bbNAttacks=PLACE_PIECE(bbNAttacks,COORDS_2_INDEX(y-2,x-1));
	if(x+1<=7 && y-2>=0) bbNAttacks=PLACE_PIECE(bbNAttacks,COORDS_2_INDEX(y-2,x+1));
	if(x+1<=7 && y+2<=7) bbNAttacks=PLACE_PIECE(bbNAttacks,COORDS_2_INDEX(y+2,x+1));
	if(x-1>=0 && y+2<=7) bbNAttacks=PLACE_PIECE(bbNAttacks,COORDS_2_INDEX(y+2,x-1));
	return bbNAttacks;
}
/* Generate King attack board based on board square index */
const U64 InitMagicMoves_K(const int square)
{
	int y=square/8,x=square%8;
	U64 bbKAttacks=0;
	if(x-1>=0) bbKAttacks=PLACE_PIECE(bbKAttacks,COORDS_2_INDEX(y,x-1));
	if(x+1<=7) bbKAttacks=PLACE_PIECE(bbKAttacks,COORDS_2_INDEX(y,x+1));
	if(y+1<=7) bbKAttacks=PLACE_PIECE(bbKAttacks,COORDS_2_INDEX(y+1,x));
	if(y-1>=0) bbKAttacks=PLACE_PIECE(bbKAttacks,COORDS_2_INDEX(y-1,x));
	if(x-1>=0 && y-1>=0) bbKAttacks=PLACE_PIECE(bbKAttacks,COORDS_2_INDEX(y-1,x-1));
	if(x+1<=7 && y-1>=0) bbKAttacks=PLACE_PIECE(bbKAttacks,COORDS_2_INDEX(y-1,x+1));
	if(x+1<=7 && y+1<=7) bbKAttacks=PLACE_PIECE(bbKAttacks,COORDS_2_INDEX(y+1,x+1));
	if(x-1>=0 && y+1<=7) bbKAttacks=PLACE_PIECE(bbKAttacks,COORDS_2_INDEX(y+1,x-1));
	return bbKAttacks;
}

const void InitMagicMoves(void)
{
	int i;

#ifdef MINIMUM_MAGIC
	U64 *MagicIndexesBishop2[64] =
	{
		MagicMoves_Bishop_DB + 4992,MagicMoves_Bishop_DB + 2624,MagicMoves_Bishop_DB + 256,MagicMoves_Bishop_DB + 896,
		MagicMoves_Bishop_DB + 1280,MagicMoves_Bishop_DB + 1664,MagicMoves_Bishop_DB + 4800,MagicMoves_Bishop_DB + 5120,
		MagicMoves_Bishop_DB + 2560,MagicMoves_Bishop_DB + 2656,MagicMoves_Bishop_DB + 288,MagicMoves_Bishop_DB + 928,
		MagicMoves_Bishop_DB + 1312,MagicMoves_Bishop_DB + 1696,MagicMoves_Bishop_DB + 4832,MagicMoves_Bishop_DB + 4928,
		MagicMoves_Bishop_DB + 0,MagicMoves_Bishop_DB + 128,MagicMoves_Bishop_DB + 320,MagicMoves_Bishop_DB + 960,
		MagicMoves_Bishop_DB + 1344,MagicMoves_Bishop_DB + 1728,MagicMoves_Bishop_DB + 2304,MagicMoves_Bishop_DB + 2432,
		MagicMoves_Bishop_DB + 32,MagicMoves_Bishop_DB + 160,MagicMoves_Bishop_DB + 448,MagicMoves_Bishop_DB + 2752,
		MagicMoves_Bishop_DB + 3776,MagicMoves_Bishop_DB + 1856,MagicMoves_Bishop_DB + 2336,MagicMoves_Bishop_DB + 2464,
		MagicMoves_Bishop_DB + 64, MagicMoves_Bishop_DB + 192,MagicMoves_Bishop_DB + 576,MagicMoves_Bishop_DB + 3264,
		MagicMoves_Bishop_DB + 4288,MagicMoves_Bishop_DB + 1984,MagicMoves_Bishop_DB + 2368,MagicMoves_Bishop_DB + 2496,
		MagicMoves_Bishop_DB + 96,MagicMoves_Bishop_DB + 224,MagicMoves_Bishop_DB + 704,MagicMoves_Bishop_DB + 1088,
		MagicMoves_Bishop_DB + 1472,MagicMoves_Bishop_DB + 2112,MagicMoves_Bishop_DB + 2400,MagicMoves_Bishop_DB + 2528,
		MagicMoves_Bishop_DB + 2592,MagicMoves_Bishop_DB + 2688,MagicMoves_Bishop_DB + 832,MagicMoves_Bishop_DB + 1216,
		MagicMoves_Bishop_DB + 1600,MagicMoves_Bishop_DB + 2240,MagicMoves_Bishop_DB + 4864,MagicMoves_Bishop_DB + 4960,
		MagicMoves_Bishop_DB + 5056,MagicMoves_Bishop_DB + 2720,MagicMoves_Bishop_DB + 864,MagicMoves_Bishop_DB + 1248,
		MagicMoves_Bishop_DB + 1632,MagicMoves_Bishop_DB + 2272,MagicMoves_Bishop_DB + 4896,MagicMoves_Bishop_DB + 5184
	};
	U64 *MagicIndexesRook2[64] =
	{
		MagicMoves_Rook_DB + 86016,MagicMoves_Rook_DB + 73728,MagicMoves_Rook_DB + 36864,MagicMoves_Rook_DB + 43008,
		MagicMoves_Rook_DB + 47104,MagicMoves_Rook_DB + 51200,MagicMoves_Rook_DB + 77824,MagicMoves_Rook_DB + 94208,
		MagicMoves_Rook_DB + 69632,MagicMoves_Rook_DB + 32768,MagicMoves_Rook_DB + 38912,MagicMoves_Rook_DB + 10240,
		MagicMoves_Rook_DB + 14336,MagicMoves_Rook_DB + 53248,MagicMoves_Rook_DB + 57344,MagicMoves_Rook_DB + 81920,
		MagicMoves_Rook_DB + 24576,MagicMoves_Rook_DB + 33792,MagicMoves_Rook_DB + 6144,MagicMoves_Rook_DB + 11264,
		MagicMoves_Rook_DB + 15360,MagicMoves_Rook_DB + 18432,MagicMoves_Rook_DB + 58368,MagicMoves_Rook_DB + 61440,
		MagicMoves_Rook_DB + 26624,MagicMoves_Rook_DB + 4096,MagicMoves_Rook_DB + 7168,MagicMoves_Rook_DB + 0,
		MagicMoves_Rook_DB + 2048,MagicMoves_Rook_DB + 19456,MagicMoves_Rook_DB + 22528,MagicMoves_Rook_DB + 63488,
		MagicMoves_Rook_DB + 28672,MagicMoves_Rook_DB + 5120,MagicMoves_Rook_DB + 8192,MagicMoves_Rook_DB + 1024,
		MagicMoves_Rook_DB + 3072,MagicMoves_Rook_DB + 20480,MagicMoves_Rook_DB + 23552,MagicMoves_Rook_DB + 65536,
		MagicMoves_Rook_DB + 30720,MagicMoves_Rook_DB + 34816,MagicMoves_Rook_DB + 9216,MagicMoves_Rook_DB + 12288,
		MagicMoves_Rook_DB + 16384,MagicMoves_Rook_DB + 21504,MagicMoves_Rook_DB + 59392,MagicMoves_Rook_DB + 67584,
		MagicMoves_Rook_DB + 71680,MagicMoves_Rook_DB + 35840,MagicMoves_Rook_DB + 39936,MagicMoves_Rook_DB + 13312,
		MagicMoves_Rook_DB + 17408,MagicMoves_Rook_DB + 54272,MagicMoves_Rook_DB + 60416,MagicMoves_Rook_DB + 83968,
		MagicMoves_Rook_DB + 90112,MagicMoves_Rook_DB + 75776,MagicMoves_Rook_DB + 40960,MagicMoves_Rook_DB + 45056,
		MagicMoves_Rook_DB + 49152,MagicMoves_Rook_DB + 55296,MagicMoves_Rook_DB + 79872,MagicMoves_Rook_DB + 98304
	};
#endif // MINIMUM_MAGIC

	/* Init file masks */
	InitFileMasks();
	/* End init file masks */

	/* Init isolani masks */
	InitIsolaniMasks();
	/* End init isolani masks */

	/* Init pawn en passant masks */
	InitPawnEnPassantMasks();
	/* End init pawn en passant masks */

	/* Generate Pawns database */
	for(i=0;i<64;i++)
	{
		MagicMoves_Pawns_DB[0][i]=InitMagicMoves_PW(i);
		MagicMoves_Pawns_DB[1][i]=InitMagicMoves_PB(i);
	}
	/* End generate Pawns database */
	
	/* Generate Knight database */
	for(i=0;i<64;i++) MagicMoves_Knight_DB[i]=InitMagicMoves_N(i);
	/* End generate Knight database */
	
	/* Generate King database */
	for(i=0;i<64;i++) MagicMoves_King_DB[i]=InitMagicMoves_K(i);
	/* End generate King database */

#ifdef HASH_PERFECT_MAGIC
	for(i=0;i<1428;i++) MagicMoves_Bishop_DB[i] = 0;
	for(i=0;i<4900;i++) MagicMoves_Rook_DB[i] = 0;
#endif
	/* Gnenerate database for Bishop */
	for(i=0;i<64;i++)
    {
		int squares[64];
		int numsquares=0;
		U64 temp=MagicMask_Bishop[i];
		while(temp)
		{
			U64 bit = temp & -temp; // asta face clear la un bit....mai rapid decat shiftarea...damn speed junkies
			squares[numsquares++] = LookupBit[(bit*0x07EDD5E59A4E28C2ULL)>>58];
			temp^=bit;
		}
		for(temp=0;temp<(((U64)(1))<<numsquares);temp++)
		{
			U64 tempocc=InitMagicMoves_Ocupare(squares, numsquares, temp);
#ifndef HASH_PERFECT_MAGIC
			BFaraMasca2 (i, tempocc) = InitMagicMoves_B (i, tempocc);
#else
			U64 moves=InitMagicMoves_B(i, tempocc);
			U64 index=(((tempocc)*MagicNumbers_Bishop[i])>>SHIFT_MINIMAL_BISHOP);
			int j;
			for(j=0;j<1428;j++)
			{
				if(!MagicMoves_Bishop_DB[j])
				{
					MagicMoves_Bishop_DB[j]=moves;
					MagicIndexesBishop[i][index]=j;
					break;
				}
				else if(MagicMoves_Bishop_DB[j]==moves)
				{
					MagicIndexesBishop[i][index]=j;
					break;
				}
			}
#endif
		}
	}
	/* End gnenerate database for Bishop */

	/* Generate database for rook */
	for(i=0;i<64;i++)
    {
		int squares[64];
		int numsquares = 0;
		U64 temp = MagicMask_Rook[i];
		while(temp)
		{
			U64 bit = temp & -temp;
			squares[numsquares++] = LookupBit[(bit*0x07EDD5E59A4E28C2ULL)>>58];
			temp^=bit;
		}
		for(temp=0;temp<(((U64)(1))<<numsquares);temp++)
		{
			U64 tempocc = InitMagicMoves_Ocupare(squares, numsquares, temp);
#ifndef HASH_PERFECT_MAGIC
			RFaraMasca2 (i, tempocc) = InitMagicMoves_R (i, tempocc);
#else
			U64 moves=InitMagicMoves_R(i, tempocc);
			U64 index=(((tempocc)*MagicNumbers_Rook[i])>>SHIFT_MINIMAL_ROOK);
			int j;
			for(j=0;j<4900;j++)
			{
				if(!MagicMoves_Rook_DB[j])
				{
					MagicMoves_Rook_DB[j]=moves;
					MagicIndexesRook[i][index] = j;
					break;
				}
				else if(MagicMoves_Rook_DB[j]==moves)
				{
					MagicIndexesRook[i][index] = j;
					break;
				}
			}
#endif
		}
    }
	/* End generate database for rook */
}
